<script setup>
// WebSocket测试组件
// 提供WebSocket连接测试、消息发送和接收功能

import { ref, onMounted, onBeforeUnmount } from "vue";

// WebSocket实例引用
const ws = ref(null);
// 消息列表
const messages = ref([]);
// 输入消息
const inputMessage = ref("");
// 连接状态
const status = ref("未连接");
// 重连尝试次数
const reconnectAttempts = ref(0);
// 最大重连尝试次数
const maxReconnectAttempts = 5;

/**
 * 连接WebSocket服务器
 * 建立WebSocket连接并设置事件监听器
 * @returns {void}
 */
const connectWebSocket = () => {
  if (ws.value && ws.value.readyState === WebSocket.OPEN) {
    return;
  }

  try {
    // 创建WebSocket连接
    ws.value = new WebSocket("ws://localhost:4646/chat");
    status.value = "正在连接...";

    // 连接打开事件
    ws.value.onopen = () => {
      status.value = "已连接";
      messages.value.push({ type: "system", content: "WebSocket连接已建立" });
      reconnectAttempts.value = 0;
    };

    // 接收消息事件
    ws.value.onmessage = (event) => {
      messages.value.push({ type: "received", content: event.data });
    };

    // 连接关闭事件
    ws.value.onclose = (event) => {
      status.value = "已断开";
      messages.value.push({
        type: "system",
        content: `WebSocket连接已关闭: ${event.code}`,
      });
      console.log(123);

      ws.value.close(1000, "用户主动关闭");

      // 在连接真正关闭后再设置为null
      setTimeout(() => {
        if (ws.value && ws.value.readyState === WebSocket.CLOSED) {
          ws.value = null;
        }
      }, 100);
      // 尝试重连
      // if (reconnectAttempts.value < maxReconnectAttempts) {
      //   reconnectAttempts.value++;
      //   messages.value.push({
      //     type: "system",
      //     content: `尝试第 ${reconnectAttempts.value} 次重连...`,
      //   });
      //   setTimeout(() => {
      //     connectWebSocket();
      //   }, 2000 * reconnectAttempts.value); // 指数退避
      // }
    };

    // 错误事件
    ws.value.onerror = (error) => {
      status.value = "连接错误";
      messages.value.push({
        type: "system",
        content: `WebSocket错误: ${error.message || "未知错误"}`,
      });
    };
  } catch (error) {
    status.value = "连接失败";
    messages.value.push({
      type: "system",
      content: `创建连接失败: ${error.message || "未知错误"}`,
    });
  }
};

/**
   * 发送WebSocket消息
   * 将用户输入的消息通过WebSocket发送到服务器
   * @returns {void}
   */
  const sendMessage = () => {
    if (!inputMessage.value.trim()) return;

    if (ws.value && ws.value.readyState === WebSocket.OPEN) {
      ws.value.send(
        JSON.stringify({
          toUserId: "user1",
          content: inputMessage.value.trim(),
          type: "text",
        })
      );
      messages.value.push({
        toUserId: "user1",
        content: inputMessage.value.trim(),
        type: "text",
      });
      inputMessage.value = "";
    } else {
      messages.value.push({
        type: "system",
        content: "WebSocket未连接，无法发送消息",
      });
    }
  };

  /**
   * 断开WebSocket连接
   * 关闭当前的WebSocket连接
   * @returns {void}
   */
  const disconnect = () => {
    if (ws.value) {
      // 调用close方法关闭连接，但不立即设置为null
      // 让onclose事件处理程序来处理连接关闭的逻辑
      ws.value.close();
      // 注意：不再在这里立即设置ws.value = null
      // 这样可以确保关闭帧能够正确发送到后端服务器
    }
  };

  /**
   * 组件挂载时的生命周期钩子
   * 组件挂载后自动连接WebSocket
   */
  onMounted(() => {
    connectWebSocket();
  });

  /**
   * 组件卸载前的生命周期钩子
   * 组件卸载前自动断开WebSocket连接
   */
  onBeforeUnmount(() => {
    disconnect();
  });
</script>

  <!-- 组件模板部分 -->
  <!-- 包含状态显示、消息列表和输入区域 -->
  <template>
    <div class="websocket-test-container">
      <h2>WebSocket测试工具</h2>

      <!-- 状态显示 -->
      <div class="status">
        <span class="status-label">连接状态：</span>
        <span :class="['status-indicator', status]" v-text="status"></span>
      </div>

      <!-- 消息列表 -->
      <div class="message-list">
        <div
          v-for="(msg, index) in messages"
          :key="index"
          :class="['message-item', msg.type]"
        >
          <span class="message-type" v-if="msg.type !== 'received'">
            {{ msg.type === "sent" ? "[发送]" : "[系统]" }}
          </span>
          <span class="message-content" v-text="msg.content"></span>
        </div>
      </div>

      <!-- 输入区域 -->
      <div class="input-area">
        <input
          v-model="inputMessage"
          type="text"
          placeholder="输入消息..."
          @keyup.enter="sendMessage"
        />
        <button @click="sendMessage" :disabled="status !== '已连接'">发送</button>
        <button @click="disconnect" :disabled="status !== '已连接'">
          断开连接
        </button>
        <button
          @click="connectWebSocket"
          :disabled="status === '已连接' || status === '正在连接...'"
        >
          连接WebSocket
        </button>
      </div>
    </div>
  </template>

  <!-- 组件样式部分 -->
  <!-- 设置组件的布局、颜色和交互样式 -->
  <style scoped>
.websocket-test-container {
  max-width: 800px;
  margin: 20px auto;
  padding: 20px;
  background-color: #f5f5f5;
  border-radius: 8px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
}

h2 {
  text-align: center;
  color: #333;
  margin-bottom: 20px;
}

.status {
  margin-bottom: 15px;
  font-weight: 500;
}

.status-indicator {
  padding: 4px 8px;
  border-radius: 4px;
  margin-left: 10px;
}

.status-indicator.已连接 {
  background-color: #4caf50;
  color: white;
}

.status-indicator.正在连接 {
  background-color: #ff9800;
  color: white;
}

.status-indicator.已断开 {
  background-color: #f44336;
  color: white;
}

.status-indicator.连接错误,
.status-indicator.连接失败,
.status-indicator.未连接 {
  background-color: #757575;
  color: white;
}

.message-list {
  max-height: 400px;
  overflow-y: auto;
  background-color: white;
  padding: 15px;
  border-radius: 4px;
  margin-bottom: 15px;
  border: 1px solid #ddd;
}

.message-item {
  margin-bottom: 10px;
  padding: 8px 12px;
  border-radius: 4px;
  word-break: break-word;
}

.message-item.sent {
  background-color: #e3f2fd;
  text-align: right;
}

.message-item.received {
  background-color: #f1f8e9;
}

.message-item.system {
  background-color: #f5f5f5;
  font-style: italic;
  color: #666;
}

.message-type {
  font-weight: bold;
  margin-right: 5px;
}

.input-area {
  display: flex;
  gap: 10px;
}

.input-area input {
  flex: 1;
  padding: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 14px;
}

.input-area button {
  padding: 10px 15px;
  border: none;
  border-radius: 4px;
  background-color: #2196f3;
  color: white;
  cursor: pointer;
  font-size: 14px;
}

.input-area button:hover:not(:disabled) {
  background-color: #1976d2;
}

.input-area button:disabled {
  background-color: #ccc;
  cursor: not-allowed;
}

.input-area button:nth-of-type(2) {
  background-color: #f44336;
}

.input-area button:nth-of-type(2):hover:not(:disabled) {
  background-color: #d32f2f;
}

.input-area button:nth-of-type(3) {
  background-color: #4caf50;
}

.input-area button:nth-of-type(3):hover:not(:disabled) {
  background-color: #388e3c;
}
</style>